package cc.geeksearch.ble

import android.Manifest
import android.bluetooth.BluetoothManager
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.app.ActivityCompat
import cc.geeksearch.ble.bean.ScanItemBean
import java.util.Timer

class WalleScanner(private val context: Context) {
    private val TAG = "WalleScanner"
    private var bluetoothLeScanner: BluetoothLeScanner? = null
    private var scanCallback: ScanCallback? = null
    private var isScanning = false
    private var timeoutTimer: Timer? = null
    private val scanResultsList = mutableListOf<ScanItemBean>() // 用于保存扫描结果的列表
    private var resultRefreshTime = 0L
    private var targetAddressList = mutableListOf<String>()
    private var scannerTargetCallback: ScannerTargetCallback? = null

    /**
     * 开始扫描
     * @param timeout 扫描超时时间，单位毫秒
     * @param targetAddress 目标地址,不为空的情况下，搜索到目标设备就停止扫描，且不把扫描结果发给LiveDataBus.scanLiveData
     */
    fun startScan(timeout: Long, targetAddress: String? = null) {
        if(!targetAddress.isNullOrEmpty() ){
            targetAddressList.add(targetAddress)
        }
        if (isScanning) {
            return
        }
        //初始化ble设配器
        val manager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?
        val mBluetoothAdapter = manager!!.adapter
        if (mBluetoothAdapter == null) {
            WalleLog.w(TAG, "设备无可用蓝牙")
            LiveDataBus.scanStatusLiveData.postValue(2)
            return
        }
        if (!mBluetoothAdapter.isEnabled) {
            WalleLog.w(TAG, "设备蓝牙未打开")
            LiveDataBus.scanStatusLiveData.postValue(2)
            return;
        }
        if (bluetoothLeScanner == null) {
            bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner()
        }
        if (scanCallback == null) {
            scanCallback = object : ScanCallback() {
                override fun onScanResult(callbackType: Int, result: ScanResult?) {
                    super.onScanResult(callbackType, result)
                    if (result == null || result.device == null || !isScanning) {
                        return
                    }
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                        if (ActivityCompat.checkSelfPermission(
                                context,
                                Manifest.permission.BLUETOOTH_CONNECT
                            ) != PackageManager.PERMISSION_GRANTED
                        ) {
                            WalleLog.e(TAG, "获取设备名称失败，无BLUETOOTH_CONNECT权限")
                        }
                    }
                    var name = result.device.name
                    if(name == null){
                        name = ""
                    }
                    val address = result.device.address
                    val rssi = result.rssi
                    WalleLog.d(TAG, "扫描到设备: $address, $name, $rssi")
                    if (targetAddressList.isEmpty()) {
                        if (WalleConfig.SCAN_FILTER_EMPTY_NAME && name.isEmpty()) {
                            return
                        }
                        if (name.isNullOrEmpty()) {
                            name = WalleConfig.SCAN_EMPTY_NAME
                        }
                        // 查找列表中是否已存在该设备地址
                        val existingResult = scanResultsList.find { it.device.address == address }
                        if (existingResult == null) {
                            // 地址不存在，添加到列表
                            scanResultsList.add(ScanItemBean(address, name, result.device, rssi))
                            scanResultsList.sortByDescending { it.rssi }
                        } else {
                            if (existingResult.rssi != rssi) {
                                // RSSI 值不同，更新数据
                                val index = scanResultsList.indexOf(existingResult)
                                scanResultsList[index] =
                                    ScanItemBean(address, name, result.device, rssi)
                                // 重新排序
                                scanResultsList.sortByDescending { it.rssi }
                            }
                            return
                        }
                        val time = System.currentTimeMillis()
                        if (time - resultRefreshTime > WalleConfig.SCAN_REPORT_DELAY_TIME) {
                            WalleLog.d(TAG, "LiveDataBus.scanLiveData onScanResult")
                            LiveDataBus.scanLiveData.postValue(scanResultsList)
                            resultRefreshTime = time
                        }
                    } else{
                        if(targetAddressList.contains(address)){
                            WalleLog.d(TAG, "扫描到目标设备，停止扫描: $address")
                            targetAddressList.remove(address)
                            if (scannerTargetCallback != null) {
                                scannerTargetCallback!!.onScanSuccess(
                                    ScanItemBean(
                                        address,
                                        name,
                                        result.device,
                                        rssi
                                    )
                                )
                            }
                            if(targetAddressList.isEmpty()){
                                WalleLog.d(TAG, "无其他目标设备需要连接，停止扫描")
                                stopScan()
                            }
                        }
                    }
                }
            }
        }
        val scanSettings = ScanSettings.Builder()
        scanSettings.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
        // 开启批量扫描
        //scanSettings.setReportDelay(200)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (ActivityCompat.checkSelfPermission(
                    context,
                    Manifest.permission.BLUETOOTH_SCAN
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                WalleLog.e(TAG, "无BLUETOOTH_SCAN权限");
                LiveDataBus.scanStatusLiveData.postValue(2)
                return
            }
        }
        scanResultsList.clear()
        WalleLog.d(TAG, "LiveDataBus.scanLiveData startScan")
        LiveDataBus.scanLiveData.postValue(scanResultsList)
        bluetoothLeScanner!!.startScan(null, scanSettings.build(), scanCallback)
        isScanning = true
        LiveDataBus.scanStatusLiveData.postValue(0)
        if (timeoutTimer != null) {
            timeoutTimer!!.cancel()
        }
        timeoutTimer = Timer()
        timeoutTimer!!.schedule(object : java.util.TimerTask() {
            override fun run() {
                if (targetAddressList.isNotEmpty() &&  scannerTargetCallback != null) {
                    scannerTargetCallback!!.onScanFailed(targetAddressList)
                    WalleLog.w(TAG, "--- 搜索超时，未搜索的设备 ---")
                    targetAddressList.forEach {
                        WalleLog.w(TAG, "--- $it ---")
                    }
                    WalleLog.w(TAG, "----------------------------")
                }
                stopScan()
            }
        }, timeout)
    }

    fun stopScan() {
        WalleLog.d(TAG, "stopScan")
        targetAddressList.clear()
        if (timeoutTimer != null) {
            timeoutTimer!!.cancel()
            timeoutTimer = null
        }
        isScanning = false
        LiveDataBus.scanLiveData.postValue(scanResultsList)
        LiveDataBus.scanStatusLiveData.postValue(1)
        if (bluetoothLeScanner == null) {
            return
        }
        if (scanCallback == null) {
            return
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (ActivityCompat.checkSelfPermission(
                    context,
                    Manifest.permission.BLUETOOTH_SCAN
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                WalleLog.e(TAG, "结束扫描失败，无BLUETOOTH_SCAN权限")
                return
            }
        }
        bluetoothLeScanner!!.stopScan(scanCallback)
        bluetoothLeScanner = null
        scanCallback = null
    }

    fun setScannerTargetCallback(callback: ScannerTargetCallback) {
        this.scannerTargetCallback = callback
    }
}